package io.github.talelin.latticy.controller.v1;

import io.github.talelin.autoconfigure.exception.NotFoundException;
import io.github.talelin.core.annotation.GroupRequired;
import io.github.talelin.core.annotation.PermissionMeta;
import io.github.talelin.latticy.common.util.ConvertGson;
import io.github.talelin.latticy.common.util.TextUtil;
import io.github.talelin.latticy.model.*;
import io.github.talelin.latticy.module.message.Response;
import io.github.talelin.latticy.module.message.WsHandler;
import io.github.talelin.latticy.service.impl.DeviceServiceImpl;
import io.github.talelin.latticy.service.impl.InsAccountInfoServiceImpl;
import io.github.talelin.latticy.service.impl.InsSendUserInfoServiceImpl;
import io.github.talelin.latticy.service.impl.MessageServiceImpl;
import io.github.talelin.latticy.vo.DeletedVO;
import io.github.talelin.latticy.vo.OperateVO;
import io.github.talelin.latticy.vo.UpdatedVO;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.socket.WebSocketSession;

import javax.validation.constraints.Positive;
import javax.validation.constraints.PositiveOrZero;

import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

/**
 * 设备控制器
 */
@RestController
@RequestMapping("/v1/device")
@Validated
@Slf4j
public class DeviceController {
    
    @Autowired
    private DeviceServiceImpl mDeviceService;
    
    @Autowired
    private InsAccountInfoServiceImpl mInsAccountInfoService;
    
    @Autowired
    private InsSendUserInfoServiceImpl mInsSendUserInfoService;
    
    @Autowired
    private MessageServiceImpl mMessageService;
    
    @Autowired
    private WsHandler wsHandler;
    
    @GetMapping("/{id}")
    public DeviceDO getDevice(@PathVariable(value = "id") @Positive(message = "{id.positive}") Integer id) {
        DeviceDO device = mDeviceService.getById(id);
        if (device == null) {
            throw new NotFoundException(10300);
        }
        return device;
    }
    
    @GetMapping("")
    public List<Device> getDevices() {
        List<Device> deviceList = mDeviceService.convertFromDO(mDeviceService.findAll());
        return deviceList;
    }
    
    @GetMapping("/search/{online}")
    public List<Device> searchDevice(@PathVariable(value = "online") @PositiveOrZero(message = "在线状态不能为空") Integer online) {
        List<Device> deviceList = mDeviceService.convertFromDO(mDeviceService.getAllDeviceByOnline(online));
        return deviceList;
    }
    
    @PutMapping("/start_task/{id}")
    public UpdatedVO updateDevice(@PathVariable("id") @Positive(message = "{id.positive}") Integer id) {
        DeviceDO device = mDeviceService.getById(id);
        if (device == null) {
            throw new NotFoundException(10300);
        }
        device.setTaskStatus(2);
        mDeviceService.updateDevice(device);
        return new UpdatedVO(17);
    }
    
    /**
     * @param id
     * @param msgTag 消息模板标签
     * @return
     */
    @PostMapping("/set_msg_tag")
    public UpdatedVO updateDeviceMsgTag(@RequestParam(name = "id") Integer id, @RequestParam(name = "msgTag") String msgTag) {
        DeviceDO device = mDeviceService.getById(id);
        if (device == null) {
            throw new NotFoundException(10300);
        }
        device.setChatMsgTag(msgTag);
        mDeviceService.updateDevice(device);
        return new UpdatedVO(200, "修改消息模板成功");
    }
    
    /**
     * 清除所有设备发送次数
     *
     * @return
     */
    @PostMapping("/update_suc_num")
    public UpdatedVO updateSucNum() {
        List<DeviceDO> deviceList = mDeviceService.getAllDeviceByOnline(1);
        if (deviceList.size() == 0 || deviceList.isEmpty()) {
            throw new NotFoundException(10300);
        }
        mDeviceService.updateSucNum(deviceList);
        return new UpdatedVO(200, "清除所有设备发送次数成功");
    }
    
    @DeleteMapping("/{id}")
    @GroupRequired
    @PermissionMeta(value = "删除设备", module = "设备")
    public DeletedVO deleteDevice(@PathVariable("id") @Positive(message = "{id.positive}") Integer id) {
        DeviceDO device = mDeviceService.getById(id);
        if (device == null) {
            throw new NotFoundException(10300);
        }
        mDeviceService.deleteById(device.getId());
        return new DeletedVO(18);
    }
    
    @PutMapping("/task/start/{id}")
    public OperateVO startTask(@PathVariable("id") @Positive(message = "{id.positive}") Integer id) {
        //获取当前设备信息
        DeviceDO device = mDeviceService.getById(id);
        
        device.setTaskStatus(2);
        mDeviceService.updateDevice(device);
        
        if (mKeepThread == null) {
            mKeepThread = new Thread(new KeepThreadRunnable());
            mKeepThread.start();
        } else {
            if (!mKeepThread.isAlive()) {
                mKeepThread.interrupt();
                mKeepThread = new Thread(new KeepThreadRunnable());
                mKeepThread.start();
            }
        }
        
        return new OperateVO(31);
        
    }
    
    @PutMapping("/task/stop/{id}")
    public OperateVO stopTask(@PathVariable("id") @Positive(message = "{id.positive}") Integer id) {
        DeviceDO device = mDeviceService.getById(id);
        if (device == null) {
            return new OperateVO(10300);
        }
        device.setTaskStatus(0);
        if (mDeviceService.updateDevice(device)) {
            return new OperateVO(31);
        } else {
            return new OperateVO(10400);
        }
    }
    
    //每天最多几次
    public static int MAX_SEND_TIMES = 1000;
    
    protected Thread mKeepThread;
    
    private class KeepThreadRunnable implements Runnable {
        
        @SneakyThrows
        @Override
        public void run() {
            List<DeviceDO> deviceList;
            
            CommandDO command;
            Response response;
            response = new Response();
            response.setAction("auto_send");
            response.setType("1");
            command = new CommandDO();
            MessageDO message = null;
            List<InsAccountInfoDO> insAccountInfoList;
            List<InsAccountInfoDO> insAccountInfoList2;
            List<InsSendUserInfoDO> receiverList;
            List<MessageDO> messageList;
            List<MessageDO> messageList2;
            
            InsAccountInfoDO insAccountInfo;
            InsSendUserInfoDO receiver = null;
            WebSocketSession session;
            
            int count = 0;
            
            while (true) {
                try {
                    log.error("任务轮询，等待中");
                    count++;
                    Thread.sleep(5000);
                    try {
                        receiverList = mInsSendUserInfoService.getListByStatus(1);
                        if (receiverList != null) {
                            for (InsSendUserInfoDO sendUserInfoDO : receiverList) {
                                //超过20分钟的
                                if ((System.currentTimeMillis() - sendUserInfoDO.getUpdateTime().getTime()) > 60 * 60 * 24 * 1000) {
                                    sendUserInfoDO.setUpdateTime(new Date());
                                    sendUserInfoDO.setStatus(0);
                                    mInsSendUserInfoService.updateInsAccountStatus(sendUserInfoDO);
                                    log.error("更新发送对象状态：" + ConvertGson.toJson(sendUserInfoDO));
                                }
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    
                    try {
                        insAccountInfoList = mInsAccountInfoService.findAllByStatus(InsAccountInfoDO.STATUS_RUNNING);
                        if (insAccountInfoList != null) {
                            for (InsAccountInfoDO insAccountInfoDO : insAccountInfoList) {
                                if ((System.currentTimeMillis() - insAccountInfoDO.getUpdateTime().getTime()) > 60 * 10 * 1000) {
                                    insAccountInfoDO.setUpdateTime(new Date());
                                    insAccountInfoDO.setStatus(InsAccountInfoDO.STATUS_NORMAL);
                                    mInsAccountInfoService.updateInsAccountInfo(insAccountInfoDO);
                                    log.error("更新账号状态：" + ConvertGson.toJson(insAccountInfoDO));
                                }
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    
                    try {
                        //超过12小时的重新可以执行任务
                        insAccountInfoList = mInsAccountInfoService.findAllByStatus(InsAccountInfoDO.STATUS_EXCEPTION);
                        if (insAccountInfoList != null) {
                            for (InsAccountInfoDO insAccountInfoDO : insAccountInfoList) {
                                if ((System.currentTimeMillis() - insAccountInfoDO.getUpdateTime().getTime()) > 60 * 60 * 2 * 1000) {
                                    insAccountInfoDO.setUpdateTime(new Date());
                                    insAccountInfoDO.setStatus(InsAccountInfoDO.STATUS_NORMAL);
                                    mInsAccountInfoService.updateInsAccountInfo(insAccountInfoDO);
                                    log.error("更新账号状态：" + ConvertGson.toJson(insAccountInfoDO));
                                }
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    
                    try {
                        deviceList = mDeviceService.getAllDeviceByTaskStatus(1);
                        if (deviceList != null) {
                            for (DeviceDO deviceDO : deviceList) {
                                if ((System.currentTimeMillis() - deviceDO.getUpdateTime().getTime()) > 60 * 60 * 1000) {
                                    deviceDO.setUpdateTime(new Date());
                                    deviceDO.setTaskStatus(2);
                                    mDeviceService.updateDevice(deviceDO);
                                    log.error("更新设备状态：" + ConvertGson.toJson(deviceDO));
                                }
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    
                    
                    //*************************以下轮询任务***
                    
                    
                    //获取接受者账号
                    receiverList = mInsSendUserInfoService.getListByStatus(0);
                    if (receiverList == null || receiverList.size() == 0) {
                        log.error("接收对象列表空");
                        continue;
                    }
                    
                    messageList = mMessageService.findAll();
                    //是否有发送内容
                    if (messageList == null || messageList.size() == 0) {
                        log.error("消息列表空");
                        continue;
                    }
                    Collections.sort(receiverList, new Comparator<InsSendUserInfoDO>() {
                        @Override
                        public int compare(InsSendUserInfoDO o1, InsSendUserInfoDO o2) {
                            int i = (int) (o1.getUpdateTime().getTime() - o2.getUpdateTime().getTime());
                            return i;
                        }
                    });
                    
                    receiver = null;
                    
                    for (InsSendUserInfoDO insSendUserInfoDO : receiverList) {
                        
                        if (insSendUserInfoDO.getStatus() == 0) {
                            
                            receiver = insSendUserInfoDO;
                            break;
                        }
                    }
                    
                    if (receiver == null) {
                        continue;
                    }
                    command.setSendName(receiver.getUsername());
                    
                    deviceList = mDeviceService.getAllDeviceByTaskStatus(2);
                    if (deviceList == null || deviceList.size() == 0) {
                        log.error("没有在线设备，等待中");
                        continue;
                    }
                    
                    
                    for (DeviceDO device : deviceList) {
                        session = wsHandler.getWebSocketSession(device.getDeviceId());
                        if (session == null) {
                            continue;
                        }
                        
                        insAccountInfo = null;
                        //获取账号信息
                        insAccountInfoList2 = mInsAccountInfoService.selectAllTaskByDeviceId(device.getDeviceId());
                        if (insAccountInfoList2 != null && insAccountInfoList2.size() > 0) {
                            for (InsAccountInfoDO insAccountInfoDO : insAccountInfoList2) {
                                //当天次数小于20次
                                if ((insAccountInfoDO.getStatus() == InsAccountInfoDO.STATUS_NORMAL || insAccountInfoDO.getStatus() == InsAccountInfoDO.STATUS_RUNNING) && insAccountInfoDO.getCount() < MAX_SEND_TIMES) {
                                    insAccountInfo = insAccountInfoDO;
                                    break;
                                }
                            }
                        }
                        if (insAccountInfo == null) {
                            //所有未开始任务的账号
                            insAccountInfoList = mInsAccountInfoService.findAllByStatus(InsAccountInfoDO.STATUS_NORMAL);
                            //是否有账号列表
                            if (insAccountInfoList == null || insAccountInfoList.size() == 0) {
                                log.error("账号列表空");
                                continue;
                            }
                            for (InsAccountInfoDO insAccountInfoDO : insAccountInfoList) {
                                if (TextUtil.isEmpty(insAccountInfoDO.getLastDeviceId()) && insAccountInfoDO.getCount() < MAX_SEND_TIMES) {
                                    insAccountInfo = insAccountInfoDO;
                                    break;
                                }
                            }
                        }
                        
                        if (insAccountInfo == null) {
                            log.error("账号列表空2");
                            continue;
                        }
                        
                        insAccountInfo.setStatus(InsAccountInfoDO.STATUS_RUNNING);
                        command.setAccount(insAccountInfo.getUsername());
                        command.setPassword(insAccountInfo.getPassword());
                        
                        
                        //根据配置获取要发送消息模板
                        messageList2 = mMessageService.getMessageByTag(device.getChatMsgTag());
                        if (messageList2 != null && messageList2.size() > 0) {
                            message = messageList2.get(0);
                        }
                        
                        if (message == null) {
                            
                            messageList = mMessageService.findAll();
                            //是否有发送内容
                            if (messageList == null || messageList.size() == 0) {
                                log.error("发送消息列表空");
                                continue;
                            }
                            message = messageList.get(0);
                        }
                        
                        if (message == null) {
                            log.error("发送消息空2");
                            continue;
                        }
                        
                        command.setMsgContent(message.getContent());
                        command.setMsgUrl(message.getImgUrl());
                        
                        
                        response.setResp(ConvertGson.toJson(command));
                        try {
                            //接收者账号更新状态
                            receiver.setStatus(1);
                            mInsSendUserInfoService.updateInsAccountStatus(receiver);
                            //ins账号更新设备id
                            insAccountInfo.setLastDeviceId(device.getDeviceId());
                            insAccountInfo.setLastDeviceTag(device.getDeviceTag());
                            mInsAccountInfoService.updateInsAccountInfo(insAccountInfo);
                            //设备工作状态更新
                            device.setTaskStatus(1);
                            mDeviceService.updateDevice(device);
                            wsHandler.sendMessage(session, ConvertGson.toJson(response));
                            
                        } catch (IOException e) {
                            log.error("轮询异常", e);
                        }
                    }
                    
                    
                } catch (Exception e) {
                    mKeepThread = null;
                    log.error("发送心跳包异常：", e);
                }
            }
        }
        
    }
}
